using Emgu.CV;
using System;
using System.Threading.Tasks;
using DualCameraApp.Services;
using SkiaSharp;

namespace DualCameraApp.Models;

public class CameraDevice : IDisposable
{
    private VideoCapture _capture;
    private bool _isRunning;
    public bool IsRunning { get { return _isRunning; } }
    
    public int CameraIndex { get; }
    public event EventHandler<Mat>? FrameCaptured;
    
    public CameraDevice(int cameraIndex)
    {
        CameraIndex = cameraIndex;
        // _capture = new VideoCapture(cameraIndex);
    }
    
    public void StartCapture()
    {
        if (_isRunning) return;
        
        _capture = new VideoCapture(CameraIndex);
        _isRunning = true;
        Task.Run(async () =>
        {
            while (_isRunning)
            {
                using var frame = new Mat();
                if (_capture.Read(frame) && !frame.IsEmpty)
                {
                    FrameCaptured?.Invoke(this, frame);
                }
                await Task.Delay(30); // ~33 FPS
            }
            Dispose();
        });
    }
    
    public void StopCapture()
    {
        _isRunning = false;
    }
    
    public void Dispose()
    {
        StopCapture();
        _capture?.Dispose();
        GC.SuppressFinalize(this);
    }
    
    public System.Drawing.Bitmap CaptureImageToBitmap()
    {
        using var frame = new Mat();
        _capture.Read(frame);
        return frame.ToBitmap();
    }
    
    public SKBitmap CaptureImageToSKBitmap()
    {
        using var frame = new Mat();
        _capture.Read(frame);
        var bitmap = ImageConverterService.MatToSKBitmapSafe(frame);
        return bitmap;
    }
    
    public (int width, int height) GetFrameSize()
    {
        var width = (int)_capture.Get(Emgu.CV.CvEnum.CapProp.FrameWidth);
        var height = (int)_capture.Get(Emgu.CV.CvEnum.CapProp.FrameHeight);
        return (width, height);
    }
}